A component type must be registered in exactly one module. If an
executable registers a component a library already registers, the
duplicate went unnoticed on Linux and was only reported at run time on
Windows (duplicate_component_id).
Add the hpx::traits::component_registered_elsewhere trait and the
HPX_COMPONENT_REGISTERED_ELSEWHERE macro a library uses to mark the
components it registers in its consumer-only header section. The
component registry macros, which all component registration macros
expand, static_assert that the component is not marked, so a second
registration fails to compile on every platform.
Mark the predefined partitioned_vector types (double, int, long long,
std::string) in partitioned_vector_component_decl.hpp, which every
partitioned_vector header includes, unless the library itself is being
compiled or HPX_HAVE_STATIC_LINKING is set.
Fixes TheHPXProject#8075
Signed-off-by: Nithurshen <nithurshen.dev@gmail.com>
Fixes #8075
Proposed Changes
hpx::traits::component_registered_elsewheretrait (andcomponent_registered_elsewhere_v) tocomponents_base, and theHPX_COMPONENT_REGISTERED_ELSEWHERE(...)macro a library uses to mark the components it registers, in the consumer-only section of its headers. The macro is variadic, so template types containing commas can be passed directly.HPX_REGISTER_MINIMAL_COMPONENT_REGISTRY_3andHPX_REGISTER_MINIMAL_COMPONENT_REGISTRY_DYNAMIC_3, which every component registration macro expands (HPX_REGISTER_COMPONENT,HPX_REGISTER_DERIVED_COMPONENT_FACTORY, their dynamic variants,HPX_REGISTER_PARTITIONED_VECTOR, ...), nowstatic_assertthatComponentType::type_holderis not marked. Registering a marked component fails to compile on every platform.partitioned_vectortypes (double,int,long long,std::string) inpartitioned_vector_component_decl.hpp, unless the library itself is being compiled (HPX_PARTITIONED_VECTOR_MODULE_EXPORTS) orHPX_HAVE_STATIC_LINKINGis set. Add a compile test and a fail-compile test inruntime_components.Any background context you want to provide?
A component type has to be registered in exactly one module. If an executable registers a component that a library already registers, both register it. On Linux the dynamic linker merges the two copies of the component's data, so this goes unnoticed. On Windows each module keeps its own copy, and the second registration is rejected at run time with
duplicate_component_id.partitioned_vector_component_decl.hpprather thanpartitioned_vector_predef.hpp. Consumers such as the segmented algorithm tests include onlyhpx/include/partitioned_vector.hpp, which doesn't include the predef header. The decl header declares the server type and every partitioned_vector header includes it.HPX_REGISTER_PARTITIONED_VECTOR_DECLARATIONdoes not include the marker.HPX_REGISTER_COARRAY_DECLARATIONreuses it for types the consumer registers itself, so including the marker would break those registrations.HPX_HAVE_STATIC_LINKINGthe library doesn't register the predefined types, the markers are skipped, and executables can register them as before.Testing (macOS, Apple Clang 21, Debug, distributed runtime):
partitioned_vector_{all_of,any_of,none,min_element,max_element,minmax_element}tests and both new compile tests. The segmented tests are compiled out on Apple Clang because of a known compiler crash, so on this platform they only confirm that the build works.HPX_HAVE_STATIC_LINKINGguard aroundHPX_REGISTER_PARTITIONED_VECTOR(int)inpartitioned_vector_2201.cpp(viapartitioned_vector.hpp) makes it fail to compile with the new diagnostic. So does removing the guard aroundHPX_REGISTER_PARTITIONED_VECTOR(double)inpartitioned_vector_view.cpp(via the predef header).Checklist